package visitor

import (
	"encoding/json"
	"encoding/xml"
	"fmt"
)

type VisitorFuncTest func(shape Shape)

type Shape interface {
	Accept(VisitorFuncTest)
}

type Circle struct {
	Radius int
}

func (c Circle) Accept(v VisitorFuncTest) {
	v(c)
}

type Rectangle struct {
	Width, Height int
}

func (r Rectangle) Accept(v VisitorFuncTest) {
	v(r)
}

func PrintSome(s Shape) {
	fmt.Println(s)
}

type OtherInfo struct {
	S Shape
	X int
}

func (o OtherInfo) Accept(fn VisitorFuncTest) {
	fmt.Println("1")
	f := func(shape Shape) {
		fmt.Println("Other Begin")
		fn(shape)
		fmt.Println("Other End")
	}
	o.S.Accept(f)
}

type OtherInfo1 struct {
	S Shape
	X int
}

func (o OtherInfo1) Accept(fn VisitorFuncTest) {
	fmt.Println("2")
	f := func(shape Shape) {
		fmt.Println("Other1 Begin")
		fn(shape)
		fmt.Println("Other1 End")
	}
	o.S.Accept(f)
}

type OtherInfo2 struct {
	S Shape
	X int
}

func (o OtherInfo2) Accept(fn VisitorFuncTest) {
	fmt.Println("3")
	f := func(shape Shape) {
		fmt.Println("Other2 Begin")
		fn(shape)
		fmt.Println("Other2 End")
	}
	o.S.Accept(f)
}

func JsonVisitor(shape Shape) {
	bytes, err := json.Marshal(shape)
	if err != nil {
		panic(err)
	}
	fmt.Println(string(bytes))
}

func XmlVisitor(shape Shape) {
	bytes, err := xml.Marshal(shape)
	if err != nil {
		panic(err)
	}
	fmt.Println(string(bytes))
}
